package com.ttxs.uaa.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ttxs.common.core.constant.Common;
import com.ttxs.uaa.entity.*;
import com.ttxs.uaa.exception.DuplicateException;
import com.ttxs.uaa.mapper.SysPlatformMapper;
import com.ttxs.uaa.mapper.SysUserMapper;
import com.ttxs.uaa.service.*;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import static com.ttxs.common.core.constant.Common.Global.*;


/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author john.yi@qq.com
 * @since 2021-08-17
 */
@Service
@RequiredArgsConstructor
public class SysPlatformServiceImpl extends ServiceImpl<SysPlatformMapper, SysPlatform> implements ISysPlatformService {
    private final ISysRoleService sysRoleService;
    private final SysUserMapper sysUserMapper;
    private final ISysUserRoleService sysUserRoleService;
    private final ISysMenuService sysMenuService;
    private final ISysRoleMenuService sysRoleMenuService;
    private final ISysDeptService sysDeptService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveAndCreateManagerUser(SysPlatform sysPlatform) {

        long count = this.count(new LambdaQueryWrapper<SysPlatform>()
                .eq(SysPlatform::getPlatformName, sysPlatform.getPlatformName()));
        if (count > 0) {
            throw new DuplicateException("平台名称已经存在");
        }
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        sysPlatform.setPlatformSecret(passwordEncoder.encode(sysPlatform.getPlatformSecret()));
        super.save(sysPlatform);
        init(sysPlatform);
        return true;
    }

    private void init(SysPlatform sysPlatform) {
        String platformId = sysPlatform.getPlatformId();
        String platformName = sysPlatform.getPlatformName();
        // 创建一个管理员角色
        SysRole sysRole = new SysRole();
        sysRole.setCreateBy(Common.Global.SYSTEM_USER);
        sysRole.setCreateTime(LocalDateTime.now());
        sysRole.setPlatformId(platformId);
        sysRole.setRoleKey(sysPlatform.getPlatformName() + "_ADMIN");
        sysRole.setRoleName(ADMIN_ROLE_NAME);
        sysRole.setRoleSort(0);
        sysRole.setStatus(Common.Status.STATUS_ENABLED);
        sysRole.setDelFlag("0");
        sysRoleService.save(sysRole);
        // 创建一个默认部门
        SysDept sysDept = new SysDept();
        sysDept.setCreateTime(LocalDateTime.now());
        sysDept.setCreateBy(Common.Global.SYSTEM_USER);
        sysDept.setDeptName(DEFAULT_DEPT_NAME);
        sysDept.setPlatformId(platformId);
        sysDeptService.save(sysDept);
        // 创建一个管理员用户
        SysUser sysUser = new SysUser();
        sysUser.setDeptId(sysDept.getDeptId());
        sysUser.setCreateTime(LocalDateTime.now());
        sysUser.setPassword(new BCryptPasswordEncoder().encode(Common.Global.DEFAULT_PASSWORD));
        sysUser.setCreateBy(Common.Global.SYSTEM_USER);
        sysUser.setNickName(ADMIN_USER_NICK_NAME);
        sysUser.setPlatformId(platformId);
        sysUser.setSex(Common.Sex.SEX_MALE);
        sysUser.setStatus(Common.Status.STATUS_ENABLED);
        sysUser.setUserName(ADMIN_USER_NAME);
        sysUser.setUserType("00");
        sysUser.setUserSalt(RandomStringUtils.randomAlphanumeric(8));
        sysUserMapper.insert(sysUser);
        // 绑定用户到角色
        SysUserRole sysUserRole = new SysUserRole(sysUser.getUserId(), sysRole.getRoleId(), platformId);
        sysUserRoleService.save(sysUserRole);
        // 授权公共菜单
        authorizeCommonMenus(sysRole.getRoleId(), platformId);
    }

    private void authorizeCommonMenus(Long roleId, String platformId) {
        Long[] menuIds = sysMenuService.getCommonMenus().stream().mapToLong(SysMenu::getMenuId)
                .boxed().toArray(Long[]::new);
        // 分配公共菜单权限到管理员角色
        List<SysRoleMenu> sysRoleMenuList = new ArrayList<>(menuIds.length);
        for (Long menuId : menuIds) {
            sysRoleMenuList.add(new SysRoleMenu(roleId, menuId, platformId));
        }
        this.sysRoleMenuService.saveBatch(sysRoleMenuList, sysRoleMenuList.size());
    }

    @Override
    public SysPlatform getByPlatformName(String platformName) {
        return getOne(new LambdaQueryWrapper<SysPlatform>().eq(SysPlatform::getPlatformName, platformName), true);
    }

    /**
     * 级联删除平台所有数据，包括用户、角色、菜单、部门等，慎用
     * @param platformId
     * @return
     */
    @Override
    public boolean removeById(Serializable platformId) {
        // 删除用户角色关联表数据
        sysUserRoleService.remove(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getPlatformId, platformId));
        // 删除用户
        sysUserMapper.delete(new LambdaQueryWrapper<SysUser>().eq(SysUser::getPlatformId, platformId));
        // 删除角色菜单关联表数据
        sysRoleMenuService.remove(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getPlatformId, platformId));
        // 删除菜单
        sysMenuService.remove(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getPlatformId, platformId));
        // 删除角色
        sysRoleService.remove(new LambdaQueryWrapper<SysRole>().eq(SysRole::getPlatformId, platformId));
        // 删除部门
        sysDeptService.remove(new LambdaQueryWrapper<SysDept>().eq(SysDept::getPlatformId, platformId));
        // 删除平台
        return getBaseMapper().deleteById(platformId) > 0;
    }
}
